package io.gitee.kotle.player.core

import android.content.Context
import android.view.TextureView
import androidx.media3.common.MediaItem
import io.gitee.kotle.player.core.impl.exoplayer.ExoPlayerImpl
import io.gitee.kotle.player.core.impl.exoplayer.IExoPlayerMode
import io.gitee.kotle.player.download.IPlayerDownload
import kotlinx.coroutines.CoroutineScope

/**
 *
 * 描述：播放器接口，定义统一的行为
 *
 * @author Jiale.Wei
 *
 * 创建时间：2023/4/12 15:45
 *
 */
interface IPlayer<Media, Model : IPlayer.IModel<Media>> {
    companion object {
        /**
         * 创建基于exoPlayer实现的播放器
         */
        fun <Model : IExoPlayerMode> exoPlayer(
            context: Context,
            impl: IPlayer<MediaItem, Model> = ExoPlayerImpl(
                context,
                createExoPlayer(context)
            )
        ): IPlayer<MediaItem, Model> = impl
    }

    sealed interface ModelState {
        /**
         * 准备中
         */
        data object Prepare : ModelState

        /**
         * 播放中
         */
        data object Play : ModelState

        /**
         * 暂停中
         */
        data object Pause : ModelState

        /**
         * 缓冲中
         */
        data object Buffer : ModelState

        /**
         * 已结束，正常播放完成
         */
        data object End : ModelState

        /**
         * 出现错误，播放出错
         */
        data object Error : ModelState

        /**
         * 已停止，没有正常播放完成，调用[stop]会回调这里
         */
        data object Stop : ModelState
    }

    /**
     * 视频的缩放类型
     */
    sealed interface VideoScaleType {
        /**
         * 居中，可左右或者上线有黑边
         */
        data object Center : VideoScaleType

        /**
         * 铺满全屏，可能会变形
         */
        data object FitXY : VideoScaleType

        /**
         * 铺满全屏，可能会有裁剪
         */
        data object CenterCrop : VideoScaleType
    }

    /**
     * 播放模式
     */
    sealed interface RepeatMode {
        object All : RepeatMode
        object One : RepeatMode
        object Off : RepeatMode
        object Shuffle : RepeatMode
    }

    /**
     * 用于构建播放对象
     */
    interface IModel<Media> {
        /**
         * 获取model的唯一id
         */
        suspend fun getMediaId(scope: CoroutineScope, player: IPlayer<Media, *>): String

        /**
         * 播放地址
         */
        suspend fun getMedia(
            scope: CoroutineScope, player: IPlayer<Media, *>, mediaId: String
        ): Media

        /**
         * 获取下载的media
         */
        suspend fun getDownloadMedia(
            scope: CoroutineScope, player: IPlayer<Media, *>, mediaId: String
        ): Media? {
            return getMedia(scope, player, mediaId)
        }

        /**
         * 获取开始的播放位置
         */
        suspend fun getPlayPosition(
            scope: CoroutineScope, player: IPlayer<Media, *>, mediaId: String, media: Media
        ) = 0L

        /**
         * 获取标题
         */
        suspend fun getTitle(
            scope: CoroutineScope, player: IPlayer<Media, *>
        ): String? = null

        /**
         * 当前model从播放器移除
         */
        suspend fun onModelDetachedFromPlayer(scope: CoroutineScope, player: IPlayer<Media, *>) {}

        /**
         * 当前关联上播放器
         */
        suspend fun onModelAttachedToPlayer(scope: CoroutineScope, player: IPlayer<Media, *>) {}
    }

    /**
     * 播放器的事件回调
     */
    interface IListener<Media, Model : IModel<Media>> {
        /**
         * 监听器被添加
         */
        fun onAttached(player: IPlayer<Media, Model>) {

        }

        /**
         * 监听器被移除
         */
        fun onDetached(player: IPlayer<Media, Model>) {

        }

        /**
         * 当调用[IPlayer.models]函数赋值的时候，会调用这里监听
         * 返回新的数据对象
         */
        fun onModelsChange(
            player: IPlayer<Media, Model>,
            oldModels: MutableList<Model>,
            newModels: MutableList<Model>
        ) {

        }

        /**
         * 定时器
         */
        suspend fun onTick(scope: CoroutineScope, player: IPlayer<Media, Model>) {

        }

        /**
         * 播放发送变化
         */
        suspend fun onModelChange(
            scope: CoroutineScope, player: IPlayer<Media, Model>, oldModel: Model?, newModel: Model
        ) {

        }

        /**
         * 准备资源
         */
        suspend fun onPrepareModel(
            scope: CoroutineScope, player: IPlayer<Media, Model>, model: Model
        ) {

        }

        fun onModelState(player: IPlayer<Media, Model>, state: ModelState) {

        }

        /***
         * 错误回调
         */
        fun onError(player: IPlayer<Media, Model>, error: Throwable) {

        }

        /**
         * 当倍速改变
         */
        fun onSpeedChange(player: IPlayer<Media, Model>, speed: Float) {

        }

        fun onVideoSizeChange(
            player: IPlayer<Media, Model>,
            width: Int,
            height: Int,
            unAppliedRotationDegrees: Int,
            pixelWidthHeightRatio: Float
        ) {

        }

        /**
         * 循环模式回调
         */
        fun onRepeatMode(player: IPlayer<Media, Model>, repeatMode: RepeatMode) {

        }

        /**
         * 画面模式发送变化
         */
        fun onVideoScaleTypeChange(player: IPlayer<Media, Model>, type: VideoScaleType) {

        }

        /**
         * 第一帧画面渲染
         */
        fun onRenderedFirstFrame(player: IPlayer<Media, Model>) {

        }
    }

    /**
     * 跟随播放器的协程，默认在主线程
     */
    val scope: CoroutineScope

    /**
     * 播放器合集
     */
    val listeners: List<IListener<Media, Model>>

    /**
     * 当前播放对象
     */
    val currentModel: Model

    /**
     * 是否有model
     */
    val hasModel: Boolean

    /**
     * 设置播放器的播放对象，不会自动播放
     * 如果当前已经有播放的流程，会停止播放
     */
    var models: MutableList<Model>

    /**
     * 设置定时器的时间间隔
     */
    var tickIntervalMillis: Long

    /**
     * 当前音量百分比，默认1f
     */
    var volume: Float

    /**
     * 当前播放器的状态
     */
    var speed: Float

    /**
     * 当前播放总时长
     */
    val duration: Long

    /**
     * 当前播放位置
     */
    var currentPosition: Long

    /**
     * 当前缓冲的位置
     */
    val bufferedPosition: Long

    /**
     * 当前的model状态
     */
    val currentModelState: ModelState

    /**
     * 下载器
     */
    var downloader: IPlayerDownload<Media>?

    /**
     * 播放器模式
     */
    var repeatMode: RepeatMode

    /**
     * 画面缩放类型
     */
    var videoScaleType: VideoScaleType

    /**
     * 当前视频尺寸
     */
    val videoSize: Triple<@ParameterName("width") Int, @ParameterName("height") Int, @ParameterName(
        "rotation"
    ) Int>

    /**
     * 资源准备
     */
    fun prepare(index: Int)

    /**
     * 播放
     */
    fun play()

    /**
     * 暂停
     */
    fun pause()

    /**
     * 停止播放
     */
    fun stop()

    /**
     * 播放下一个
     */
    fun next()

    /**
     * 播放上一个
     */
    fun previous()

    /**
     * 添加监听
     */
    fun addListener(listener: IListener<Media, Model>?)

    /**
     * 移除监听
     */
    fun removeListener(listener: IListener<Media, Model>?)

    /**
     * 开始定时器
     */
    fun startTick()

    /**
     * 停止定时器
     */
    fun stopTick()

    /**
     * 关联画面
     */
    fun attachTextureView(view: TextureView?)

    /**
     * 释放资源
     */
    fun release()
}